From 8b07052b162e4bdf423d6e39a9999a551906daf5 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 11 Sep 2014 14:09:44 -0700 Subject: [PATCH] Fix list_files_git for paths in subdirs of a repo list_files_git previously assumed that the package was always at the root of the git repository. This broke when trying to list files for a package in a subdirectory of a repo, or in other cases, e.g. if the user's home directory is a git repo. --- src/cargo/sources/path.rs | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index 7f7536b67..ecaf54143 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -69,16 +69,27 @@ impl PathSource { /// are relevant for building this package, but it also contains logic to /// use other methods like .gitignore to filter the list of files. pub fn list_files(&self, pkg: &Package) -> CargoResult> { - let candidates = match git2::Repository::open(&self.path) { + let root = pkg.get_manifest_path().dir_path(); + + // Check whether the package itself is a git repository. + let candidates = match git2::Repository::open(&root) { Ok(repo) => try!(self.list_files_git(pkg, repo)), - Err(..) => try!(self.list_files_walk(pkg)), + + // If not, check whether the package is in a sub-directory of the main repository. + Err(..) if self.path.is_ancestor_of(&root) => { + match git2::Repository::open(&self.path) { + Ok(repo) => try!(self.list_files_git(pkg, repo)), + _ => try!(self.list_files_walk(pkg)) + } + } + // If neither is true, fall back to walking the filesystem. + _ => try!(self.list_files_walk(pkg)) }; let pats = pkg.get_manifest().get_exclude().iter().map(|p| { Pattern::new(p.as_slice()) }).collect::>(); - let root = pkg.get_manifest_path().dir_path(); Ok(candidates.move_iter().filter(|candidate| { let relative_path = candidate.path_relative_from(&root).unwrap(); !pats.iter().any(|p| p.matches_path(&relative_path)) && @@ -88,25 +99,38 @@ impl PathSource { fn list_files_git(&self, pkg: &Package, repo: git2::Repository) -> CargoResult> { + warn!("list_files_git {}", pkg.get_package_id()); let index = try!(repo.index()); + let root = match repo.workdir() { + Some(dir) => dir, + None => return Err(internal_error("Can't list files on a bare repository.", "")), + }; + let pkg_path = pkg.get_manifest_path().dir_path(); + let mut ret = Vec::new(); 'outer: for i in range(0, index.len()) { let entry = match index.get(i) { Some(e) => e, None => continue }; let fname = entry.path.as_bytes_no_nul(); - let path = pkg.get_manifest_path().dir_path().join(fname); + let file_path = root.join(fname); + + // Filter out files outside this package. + if !pkg_path.is_ancestor_of(&file_path) { continue } // Filter out Cargo.lock and target always if fname == b"Cargo.lock" { continue } if fname == b"target" { continue } - // Filter out all other packages - for pkg in self.packages.iter().filter(|p| *p != pkg) { - let pkg_path = pkg.get_manifest_path().dir_path(); - if pkg_path.is_ancestor_of(&path) { continue 'outer; } + // Filter out sub-packages of this package + for other_pkg in self.packages.iter().filter(|p| *p != pkg) { + let other_path = other_pkg.get_manifest_path().dir_path(); + if pkg_path.is_ancestor_of(&other_path) && other_path.is_ancestor_of(&file_path) { + continue 'outer; + } } // We found a file! - ret.push(path); + warn!(" found {}", file_path.display()); + ret.push(file_path); } Ok(ret) } @@ -193,6 +217,7 @@ impl Source for PathSource { // condition where this path was rm'ed - either way, // we can ignore the error and treat the path's mtime // as 0. + warn!("{} {}", file.stat().map(|s| s.modified).unwrap_or(0), file.display()); max = cmp::max(max, file.stat().map(|s| s.modified).unwrap_or(0)); } log!(5, "fingerprint {}: {}", self.path.display(), max); -- 2.30.2